package com.ruleengine.frame.impl;

import org.apache.log4j.Logger;

import com.ruleengine.context.IWorkflowConext;
import com.ruleengine.endpoint.data.IEndpointData;
import com.ruleengine.executer.InstructionExecuter;
import com.ruleengine.executer.exception.InstructionExecuteException;
import com.ruleengine.instruction.Instruction;
import com.ruleengine.instruction.InstructionManager;
import com.ruleengine.instruction.InstructionSet;

public class ExecutorRunner implements Runnable {
    private static Logger logger = Logger.getLogger(ExecutorRunner.class);
    private IWorkflowConext context;
    private IEndpointData data;
    private boolean isCallback = false;

    public ExecutorRunner(IWorkflowConext context, IEndpointData data) {
        this.context = context;
        this.data = data;
    }

    public boolean isCallback() {
        return isCallback;
    }

    public void setCallback(boolean isCallback) {
        this.isCallback = isCallback;
    }

    public void run() {
        // TODO Auto-generated method stub
        while (true) {
            try {
                if(isCallback==true){
                    //回调进度框架，需要检查是否回调时出错了
                    isCallback = false;
                    if(context.getExceptionCause() != null){
                        //回调中出现了异常
                        throw context.getExceptionCause();
                    }else{
                        //成功执行
                        // pc计数器+1
                        logger.debug(" excute the nonblocking type of instruction is successfully, re-enter the workflow frame");
                        context.addPcCount(1);
                    }
                }
                // 获取当前指令
                Instruction in = context.getCurrentInstruction();
                // 获取指令执行器
                InstructionExecuter execute = InstructionManager.getInstance()
                        .getInstructionExecuter(in.getInstructionType());
                logger.debug(Thread.currentThread()
                        + " excute the instruction >>> " + in);

                // 执行指令
                execute.execute(context, data, in);

                if (in.isSynchronize()) {
                    // 同步指令，且不是terminate指令，则继续执行
                    // pc计数器+1
                    context.addPcCount(1);
                } else {
                    // 异步指令，则结束当前执行片段
                    break;
                }
            } catch (Exception e) {
                logger.error("execute the instruction {"
                        + context.getCurrentInstruction()
                        + "} error, trying to handle the exception ", e);
                // 处理异常
                InstructionSet set = context.getInstructionSet();
                int catchIdx = set.getExceptionHandler(context.getPcCount(), e);
                if (catchIdx != -1) {
                    // 当前指令配置了异常处理
                    context.setPcCount(catchIdx);
                    // 传递异常到下一个指令中
                    context.setExceptionCause(e);
                } else {
                    throw new RuntimeException(
                            "can't find a exception handler ", e);
                }
            }
        }

    }

    public void preProcess(IWorkflowConext context, Object data)
            throws InstructionExecuteException {
        if (context.getInstructionSet() == null) {
            // 为初始化指令集
        }
    }

    public void preInterceptor(IWorkflowConext context, Object data)
            throws InstructionExecuteException {

    }

}